#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>

#include "fdk-aac/aacdecoder_lib.h"
#include "maz/assert.h"

int dlvl = DINF;

int main(int argc, char *argv[])
{
    int i = 0;
    int ret = -1;
    int ifd = 0;
    int ofd = -1;

    int hdlen = 7;              // AAC ADTS 信息头长度
    int inlen = 0;              // AAC Frame 长度
    uint8_t *inbuf = NULL;      // AAC Frame 数据
    int outlen = 2048;          // PCM Frame 长度
    uint8_t *outbuf = NULL;     // PCM Frame 数据

    /* AAC 编码库配置 */
    HANDLE_AACDECODER handle = NULL;

    if (argc != 3)
    {
        dlog(DERR, "usage: %s <iname> <oname>\n", argv[0]);
        return -1;
    }

    ifd = open(argv[1], O_RDWR, 0777);
    MAZASSERT_RETVAL(ifd < 0, -1, "open aac file failed");

    ofd = open(argv[2], O_RDWR | O_CREAT, 0777);
    MAZASSERT_RETVAL(ofd < 0, -1, "create pcm file failed");

    handle = aacDecoder_Open(TT_MP4_ADTS, 1);
    MAZASSERT_RETVAL(NULL == handle, -1, "create pcm file failed");

    // aacDecoder_SetParam(handle, AAC_CONCEAL_METHOD, 0);

    inbuf = malloc(outlen);
    MAZASSERT_RETVAL(NULL == inbuf, -1, "err: malloc the inbuf failed");

    outbuf = malloc(outlen);
    MAZASSERT_RETVAL(NULL == outbuf, -1, "err: malloc the outbuf failed");

    while(1)
    {
        int rcnt = 0;

        rcnt = read(ifd, inbuf, hdlen);
        dlog(DIGN, "rcnt = %d", rcnt);
        dlog(DIGN, "0x%02x/0x%02x", inbuf[0], inbuf[1]);
        if(rcnt != hdlen)
        {
            break;
        }

        if(inbuf[0] != 0xff || (inbuf[1] & 0xf0) != 0xf0)
        {
            dlog(DERR, "err: sync word not match.");
            break;
        }

        inlen = ((inbuf[3] & 0x03) << 11) | (inbuf[4] << 3) | ((inbuf[5] & 0xe0) >> 5);
        dlog(DBUG, "%d", inlen);

        rcnt = read(ifd, inbuf + hdlen, inlen - hdlen);
        if(rcnt != (inlen - hdlen))
        {
            printf("finish.\n");
            break;
        }

        ret = aacDecoder_Fill(handle, &inbuf, &inlen, &inlen);
        MAZASSERT_RETVAL(ret, ret, "err: aacDecoder_Fill, ret = %d", ret);

        ret = aacDecoder_DecodeFrame(handle, (uint16_t *)outbuf, outlen, 0);
        MAZASSERT_RETVAL(ret, ret, "err: aacDecoder_DecodeFrame, ret = %d", ret);

        CStreamInfo *info = aacDecoder_GetStreamInfo(handle);

        write(ofd, outbuf, info->frameSize * 2);
        dlog(DBUG, "insize = %d, outsize = %d\n", inlen, info->frameSize * 2);
    }

    aacDecoder_Close(handle);

    free(inbuf);

    ret = close(ofd);
    MAZASSERT_RETVAL(ret, ret, "err: close fd_aenc ret = %d", ret);

    ret = close(ifd);
    MAZASSERT_RETVAL(ret, ret, "err: close fd ret = %d", ret);

    return 0;
}

